﻿using System.ComponentModel;
using Inspire.Entities;
using Inspire.Main.Exceptions;
using System;
using System.Collections;

namespace Inspire.DataStructures
{
    /// <summary>
    /// NewCustomFieldSource: Used by creation pages to back the custom field tab. These are custom field entries that have not been persisted to the data base, yet.
    /// </summary>
    public class NewCustomFieldSource : INotifyPropertyChanged
    {
        /// <summary>
        /// The CustomFieldType that this field is derived from.
        /// </summary>
        private CustomFieldType _customFieldType = null;
        public CustomFieldType CustomFieldType
        {
            get
            {
                return this._customFieldType;
            }
            set
            {
                // Ensure the new value is acceptable
                if (value == null)
                {
                    throw new InvalidValueAssignmentException("Attempted to assign invalid value [null] to property [CustomFieldType].");
                }
                else
                {
                    // Set the Field Type
                    this._customFieldType = value;
                    this.NotifyPropertyChanged("CustomFieldType");

                    // Initialize a Value
                    this.Reset();
                }
            }
        }

        /// <summary>
        /// FieldValue: The value of the Custom Field.
        /// </summary>
        private Object _fieldValue = "";
        public Object FieldValue
        {
            get
            {
                return this._fieldValue;
            }
            set
            {
                if (value == null)
                {
                    throw new InvalidValueAssignmentException("Attempted to assign invalid value [null] to property [FieldValue].");
                }
                else
                {
                    this._fieldValue = value;
                    this.NotifyPropertyChanged("FieldValue");
                }
            }
        }

        /// <summary>
        /// When editing an existing Custom Field, this will contain that field. This allows NewCustomFieldSource to be re-used for existing fields.
        /// In these cases, the field may be updated or deleted, but not re-created.
        /// </summary>
        private CustomField _existingField;
        public CustomField ExistingField
        {
            get
            {
                return this._existingField;
            }
            set
            {
                if (value == null)
                {
                    throw new InvalidValueAssignmentException("Attempted to assign invalid value [null] to property [FieldValue].");
                }
                else
                {
                    this._existingField = value;
                    this.NotifyPropertyChanged("ExistingField");
                }
            }
        }

        /// <summary>
        /// Resets the FieldValue to a default value appropriate to the data type of this Custom Field.
        /// </summary>
        public void Reset()
        {
            // Some data types (e.g. System.String) don't have a default constructor and cannot be
            // created by the CreateInstance() method.
            try
            {
                if (!(this.CustomFieldType.Type.Equals("String")))
                {
                    // Try to create a new default object
                    this.FieldValue = Activator.CreateInstance(Type.GetType("System." + this.CustomFieldType.Type));
                }
                else
                {
                    this.FieldValue = "";
                }
            }
            catch (MissingMethodException ex)
            {
                // Print the message message
                Console.Out.WriteLine(ex.Message);

                // Try just using a blank string
                this.FieldValue = "";
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyName)
        {
            PropertyChanged = null;
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }
}
